package model;

import java.util.ArrayList;

import util.IniParameters;
import controls.CenterTimer;

public class NormalTaskUtility extends Tasks {
	private boolean futileWaiting = false;

	public void addTask(TaskElement element) {
		int source = element.getSource();
		int dest = element.getDest();

		ArrayList<TaskElement> list;
		taskNumber++;

		if (source > dest) {
			if (!downMap.containsKey(String.valueOf(source))) {
				list = new ArrayList<TaskElement>();
				list.add(element);
				downMap.put(String.valueOf(source), list);
			} else {
				list = downMap.get(String.valueOf(source));
				list.add(element);
			}
		} else if (source < dest) {
			if (!upMap.containsKey(String.valueOf(source))) {
				list = new ArrayList<TaskElement>();
				list.add(element);
				upMap.put(String.valueOf(source), list);
			} else {
				list = upMap.get(String.valueOf(source));
				list.add(element);
			}
		}// end else if
	}

	public void addTask(int source, int dest) {
		TaskElement element = new TaskElement(source, dest);
		addTask(element);
	}

	// return true to indicate waiting is needed
	public boolean doingTask(int currentLevel, int direction) { // 1 for up, 0
																// for stable,
																// -1 for down
		ArrayList<TaskElement> list;
		TaskElement temp;
		TaskElement[] toRemove;
		int size;
		int index = 0;

		boolean isWaitingNeeded = false;

		if (direction == 1) {
			list = upMap.get(String.valueOf(currentLevel));
			isLoading = false;

			if (list != null && list.size() != 0) {
				size = list.size();
				toRemove = new TaskElement[size];

				// when the elevator is full and there are persons waiting in
				// current level,
				// the elevator must waiting for 1s but doing nothing
				if (isFull && futileWaiting == false) {
					futileWaiting = true;
					return true;
				} else if (isFull && futileWaiting == true) {
					futileWaiting = false;
					return false;
				}

				for (int i = 0; i < size && !isFull; i++) {
					temp = list.get(i);

					if ((int) temp.getTimeUnit() <= 0) {
						CenterTimer.getInstance().removeFromRight(temp);

						state.add(temp);
						toRemove[index] = temp;
						index++;

						isLoading = true;
					} else {
						isWaitingNeeded = true;
					}

					// check whether the elevator is full
					if (state.size() >= IniParameters.maxNumberOfPeronsInElevator) {
						isFull = true;
					}
				} // end for

				for (int i = 0; i < index; i++) {
					list.remove(toRemove[i]);
				}
			}

		} else if (direction == -1) {
			list = downMap.get(String.valueOf(currentLevel));
			isLoading = false;

			if (list != null && list.size() != 0) {
				size = list.size();
				toRemove = new TaskElement[size];

				// when the elevator is full and there are persons waiting in
				// current level,
				// the elevator must waiting for 1s but doing nothing
				if (isFull && futileWaiting == false) {
					futileWaiting = true;
					return true;
				} else if (isFull && futileWaiting == true) {
					futileWaiting = false;
					return false;
				}

				for (int i = 0; i < size && !isFull; i++) {
					temp = list.get(i);

					if ((int) temp.getTimeUnit() <= 0) {
						CenterTimer.getInstance().removeFromRight(temp);

						state.add(temp);
						toRemove[index] = temp;
						index++;

						isLoading = true;
					} else {
						isWaitingNeeded = true;
					}

					// check whether the elevator is full
					if (state.size() >= IniParameters.maxNumberOfPeronsInElevator)
						isFull = true;
				}

				for (int i = 0; i < index; i++) {
					list.remove(toRemove[i]);
				}

			}
		}// end else if(direction == -1)

		if (isWaitingNeeded)
			return true;
		else if (!isWaitingNeeded && isLoading)
			return true;
		else
			return false;

	}

	// return true for waiting when persons left
	public boolean finishTask(int currentLevel) {
		TaskElement temp;
		int size = state.size();

		TaskElement[] toRemove = new TaskElement[size];
		int index = 0;

		isUnloading = false;
		for (int i = 0; i < size; i++) {
			temp = state.get(i);
			if (temp.getDest() == currentLevel) {
				toRemove[index] = temp;
				index++;
				isUnloading = true;
			}
		}

		if (index > 0)
			isFull = false;

		for (int i = 0; i < index; i++) {
			state.remove(toRemove[i]);
		}

		return isUnloading;
	}
}
